//一个用于自增的id
let $id = 0;


function defineWatch($, core, wc) {
  if (typeof wc === 'object') {
    let coreData = {};

    for (let k in wc) {
      if (wc.hasOwnProperty(k)) {
        let wf = wc[k];
        if (typeof wf === 'function') {
          if (!core.hasOwnProperty(k)) {
            core[k] = null;
          }
          let dp = Reflect.getOwnPropertyDescriptor(core, k);

          if (dp) {
            if (dp.configurable) {
              let set = dp.set;
              let get = dp.get;
              if (set || get) {
                if (set) {
                  dp.set = v => {
                    let o = core[k];
                    set(v);
                    coreData[k] = v;
                    wf.call($, v, o, coreData);
                    if (coreData[k] !== v) {
                      set(coreData[k]);
                    }
                  };
                }
                if (get) {
                  dp.get = () => {
                    return get();
                  };
                }
              } else {
                coreData[k] = core[k];
                if (dp.writable) {
                  dp.set = v => {
                    coreData[k] = v;
                    wf.call($, v, core[k], coreData);
                  };
                }
                dp.get = () => {
                  return coreData[k];
                };

                delete dp.writable
                delete dp.value;
              }
              Reflect.defineProperty(core, k, dp);
            }
          }

        }
      }
    }
  }

}


function defineCalculate($, wc) {
  if (typeof wc === 'object') {
    for (let k in wc) {
      if (wc.hasOwnProperty(k)) {
        let wf = wc[k];
        if (typeof wf === 'function') {

          //不能将已经存在的属性定义为计算属性
          if (!$.hasOwnProperty(k)) {
            let dp = {
              configurable: true,
              enumerable: true,
              get() {
                return wf.call($);
              },
              set(v) {
                return true;
              }
            };
            Reflect.defineProperty($, k, dp);
          }

        }
      }
    }
  }

}

/*
  事件注册中心

  o.on('a',()=>{

    xxxx

  });


  o.emit();

 */

//定义事件
function defineEventCenter($, ek, k1, k2, rk, rk2, ck1, ck2, ot) {


  let c = {};

  let on = (e, func) => {
    let tb = c[e];
    if (!tb) {
      tb = c[e] = [];
    }
    tb.push(func);
  };


  Reflect.defineProperty($, k1, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: on
  });


  Reflect.defineProperty($, k2, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: on
  });

  let onceMap = {};

  let once = (e, func) => {
    let tb = onceMap[e];
    if (!tb) {
      tb = onceMap[e] = [];
    }

    let of = function () {
      try {
        func(arguments);
      }catch (e) {
      }
      while (true) {
        let i = tb.findIndex(o => o === func);
        if (i === -1) {
          break
        }
        tb.splice(i, 1);
      }
      if (tb.length === 0) {
        delete c[e];
      }
    };

    tb.push(of);
  };

  //监听一次
  Reflect.defineProperty($, ot, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: once
  });


  let removeListener = (e, func) => {

    let tb = c[e];
    if (!tb) {
      return
    }

    while (true) {
      let i = tb.findIndex(o => o === func);
      if (i === -1) {
        break
      }
      tb.splice(i, 1);
    }
    if (tb.length === 0) {
      delete c[e];
    }
  }


  Reflect.defineProperty($, rk, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: removeListener
  });

  Reflect.defineProperty($, rk2, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: removeListener
  });


  let clearListener = (e) => {
   // debugger
    //全部清理干净
    delete c[e];
  };


  Reflect.defineProperty($, ck1, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: clearListener
  });

  Reflect.defineProperty($, ck2, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: clearListener
  });


  let emit = function () {
    let as = arguments;
    let e = as[0];

    let tb = c[e];
    if (tb) {
      let ta = [];
      for (let i = 1; i < as.length; i++) {
        ta.push(as[i]);
      }
      tb.forEach(z => {
        try {
          z(...ta);
        } catch (e) {
        }
      })
    }
  };


  Reflect.defineProperty($, ek, {
    configurable: true,
    enumerable: false,
    writable: false,
    value: emit
  });

}


class Service {

  $ = {};

  addListenerKey = 'addListener';

  removeListenerKey = 'removeListener';

  clearListenerKey = 'clearListener';

  emitKey = 'emit';

  onKey = 'on';

  ronKey = 'ron';

  conKey = 'con';

  onceKey = 'once';

  //服务key
  serviceKey = '$'

  //内核键
  coreKey = 'core'

  //id
  idKey = 'id'

  //初始化器
  initializerKey = 'init'

  //挂载后行为
  mountedKey = 'mounted'

  //简体core内部变化的监听器获取键
  watchCoreKey = 'watchCore';

  //自我监听
  watchKey = 'watch';

  //自己计算属性
  calculateKey = 'calculate';

  //配置属性
  configsKey = 'configs';


  enh(core, serviceType, configs) {

    if (typeof serviceType !== 'function') {
      throw new Error('服务类型必须是函数')
    }

    if (typeof core !== 'object') {
      throw new Error('被增强的必须是对象')
    }

    let $ = new serviceType();

    if (configs && typeof configs === 'object') {
      //值复制操作
      for (let i in configs) {
        if (configs.hasOwnProperty(i)) {
          $[i] = configs[i];
        }
      }
      $[this.configsKey] = {
        ...configs
      };
    }


    //对id赋值
    $[this.idKey] = "id_" + ($id++);

    //定义core
    Reflect.defineProperty($, this.coreKey, {
      configurable: false,
      enumerable: false,
      writable: false,
      value: core
    })

    //创建core的监听

    if ($[this.watchCoreKey]) {

      let wc = $[this.watchCoreKey];
      if (typeof wc === 'function') {
        wc = wc.call($);
      }
      defineWatch($, core, wc);

    }


    //监听自我属性变化
    if ($[this.watchKey]) {

      let wc = $[this.watchKey];
      if (typeof wc === 'function') {
        wc = wc.call($);
      }

      defineWatch($, $, wc);

    }

    if ($[this.calculateKey]) {

      let wc = $[this.calculateKey];
      if (typeof wc === 'function') {
        wc = wc.call($);
      }
      defineCalculate($, wc);
    }

    defineEventCenter($, this.emitKey, this.addListenerKey, this.onKey, this.removeListenerKey, this.ronKey,
      this.clearListenerKey,
      this.conKey,
      this.onceKey
    );

    //代理
    $ = new Proxy($, {
      get(target, p) {
        let r = target[p]
        if (typeof r === 'function') { // 对函数做一层 处理防止其函数的this this指代被篡改
          return function () {
            return r.call($, ...arguments);
          };
        }
        return r;
      }
    })

    Reflect.defineProperty(core, this.serviceKey, {
      configurable: false,
      enumerable: false,
      writable: false,
      value: $
    });


    //初始化
    if (typeof $[this.initializerKey] === 'function') {
      $[this.initializerKey]();
    }


    //vue 中存在一个公共问题,使用v-for创建出来的子视图无法更新ui,这是vue本身的文本不是该辅助类的问题

    this.$ = $;


    if (typeof $[this.mountedKey] === 'function') {
      $[this.mountedKey]();
    }

    //将core返回
    return core;

  }

  mkSv(serviceType, configs) {

    //返回的是服务本身
    return this.enh({}, serviceType, configs).$;

  }


}


export default Service;
